package com.smarttest.common.util.protocol;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.smarttest.common.beans.protolcol.CTBox;
import com.smarttest.common.beans.protolcol.CTBox12Alarm;
import com.smarttest.common.beans.protolcol.ColdChains;
import com.smarttest.common.beans.protolcol.Index;
import com.smarttest.common.beans.protolcol.LctTraceManager;
import com.smarttest.common.beans.protolcol.Location;
import com.smarttest.common.beans.protolcol.SmartMessage;

public class CmdColdChainDataParse {
	    protected Logger logger = LoggerFactory.getLogger(this.getClass());
	    protected LctTraceManager  lctTraceManager;

	    /**冷链异常*/
	    private String exception = StringUtils.EMPTY;

	    /**CTBOX12冷链报警事件*/
	    private ColdChains coldChains;
	    
	    
	    /**计算开始时间*/
	    private long startTime = System.currentTimeMillis();

	    public List<CTBox> parse(SmartMessage msg) {
	        //解析消息体
	    	List<CTBox> ctbs = getCTBoxs(msg);
	        return ctbs;
	    }


	    private List<CTBox> getCTBoxs(SmartMessage msg) {
	    	List<CTBox> ctbs = null;
	        try {
	            byte[] data = msg.getData();
	            if (data == null || data.length <= 0)
	                return null;
	            Index index = new Index();

	            ByteUtil.parseWord(data, index); //信息长度
	            //			System.out.println(length);
	            int count = data[index.add()]; //信息条数
	            if (count < 1) {
	                return null;
	            }
	            coldChains = new ColdChains();
	            ctbs = new ArrayList<CTBox>(count);
	            CTBox ctb;
	            //由于一个消息可能包含多个数据
	            for (int i = 0; i < count; i++) {
	                ctb = getCTBox(msg.getImei(), data, index);
	                if (ctb != null) {
	                	ctb.setImei(msg.getImei());
	                    ctbs.add(ctb); //add
	                    if (logger.isDebugEnabled()) {
	                        logger.debug(ctb.toString());
	                    }
	                }
	                //另一种方式，可以在此将数据加入插入队列中。
	            }
	        } catch (Exception e) {
	            logger.error(e.getMessage(), e);
	        }
	        return ctbs;
	    }

	    /**
	     * 解析具体消息：保存成gtp:0,t1:0|26.6|23.5|27.3|70.0|63.3|80.0;t2:23|26.3|21|29|50|30|80.1,s:20,of:111,
	     * @param data
	     * @param index
	     * @param len
	     * @return
	     */
	    private CTBox getCTBox(String imei, byte[] data, Index index) {
	        int len = data[index.add()]; //本组数据的总长度
	        if (len < 1) {
	            return null;
	        }
	        byte[] subData = new byte[len];
	        System.arraycopy(data, index.get(), subData, 0, len); //本组数据
	        index.add(len);
	        int t; //设备自身温度
	        int speed; //车辆行驶速度
	        int acc; //ACC状态 0:关；1：开；2：无法获取状态
	        int compressor; //压缩机状态0:关；1：开；2：无法获取状态
	        int door; //门开关状态0:关；1：开；2：无法获取状态

	        //处理
	        Index subIndex = new Index();
	        CTBox ctb = new CTBox();
	        ctb.setImei(imei);
	        StringBuilder sb = new StringBuilder(40);
	        //采集时间
	        Calendar calendar = Calendar.getInstance();
	        calendar.set(2000 + ByteUtil.bcdDec(subData[subIndex.add()]),
	            ByteUtil.bcdDec(subData[subIndex.add()]) - 1, ByteUtil.bcdDec(subData[subIndex.add()]),
	            ByteUtil.bcdDec(subData[subIndex.add()]), ByteUtil.bcdDec(subData[subIndex.add()]),
	            ByteUtil.bcdDec(subData[subIndex.add()]));
	        ctb.setTime(calendar.getTime());

	        //设备自身温度
	        sb.append("gtp:");
	        t = ByteUtil.parseByte2IntSign(subData, subIndex);
	        sb.append(t).append(",");

	        //经纬度			location 
	        double lng = (ByteUtil.parseDWord(subData, subIndex)) / 1000000.0;
	        double lat = (ByteUtil.parseDWord(subData, subIndex)) / 1000000.0;
	        Location location = new Location(calendar.getTime(), lat, 0, lng,0,0,0,0);
	        location.setImei(imei);
	        ctb.setLoc(location);

	        //车辆行驶速度
	        speed = ByteUtil.parseWord(subData, subIndex);
	        //ACC状态
	        acc = subData[subIndex.add()];
	        //压缩机状态
	        compressor = subData[subIndex.add()];
	        //门开关状态
	        door = subData[subIndex.add()];

	        //总通道数
	        int dp = ByteUtil.parseByte2Int(subData, subIndex);
	        //温湿度报警字
	        byte alarmByte;
	        String res = StringUtils.EMPTY;

	        //遍历通道 温湿度
	        for (int i = 0; i < dp; i++) {
	            //重置异常值为默认
	            exception = StringUtils.EMPTY;

	            sb.append("t");
	            //通道号
	            int channelId = ByteUtil.parseByte2Int(subData, subIndex);
	            sb.append(channelId).append(":");
	            //温湿度报警字
	            alarmByte = subData[subIndex.add()];
	            sb.append((byte) (alarmByte >> 4) & 0xf);
	            sb.append((byte) (alarmByte) & 0xf);
	            sb.append("|");

	            //当前有效温度
	            float t1 = new Float(ByteUtil.parseWordSign(subData, subIndex)) / 10;
	            res = analyTemperature(imei, subData, subIndex);
	            if (StringUtils.isBlank(res)) {
	                sb.append(t1 > 3000 ? "" : t1).append("|");
	            } else {
	                sb.append(res).append("|");
	            }

	            //最低温度
	            float lowT = new Float(ByteUtil.parseWordSign(subData, subIndex)) / 10;
	            res = analyTemperature(imei,subData, subIndex);
	            if (StringUtils.isBlank(res)) {
	                sb.append(lowT > 3000 ? "" : lowT).append("|");
	            } else {
	                sb.append(res).append("|");
	            }

	            //最高温度
	            float highT = new Float(ByteUtil.parseWordSign(subData, subIndex)) / 10;
	            res = analyTemperature(imei,subData, subIndex);
	            if (StringUtils.isBlank(res)) {
	                sb.append(highT > 3000 ? "" : highT).append("|");
	            } else {
	                sb.append(res).append("|");
	            }

	            //即时有效湿度
	            float m1 = new Float(ByteUtil.parseWord(subData, subIndex)) / 10;
	            res = analyTemperature(imei,subData, subIndex);
	            if (StringUtils.isBlank(res)) {
	                sb.append(m1 > 3000 ? "-" : m1).append("|");
	            } else {
	                sb.append(res).append("|");
	            }

	            //最低湿度
	            float lowm = new Float(ByteUtil.parseWord(subData, subIndex)) / 10;
	            res = analyTemperature(imei,subData, subIndex);
	            if (StringUtils.isBlank(res)) {
	                sb.append(lowm > 3000 ? "-" : lowm).append("|");
	            } else {
	                sb.append(res).append("|");
	            }

	            //最高湿度
	            float highm = new Float(ByteUtil.parseWord(subData, subIndex)) / 10;
	            res = analyTemperature(imei,subData, subIndex);
	            if (StringUtils.isBlank(res)) {
	                sb.append(highm > 3000 ? "-" : highm);
	            } else {
	                sb.append(res);
	            }
	            sb.append(";");
	            
	            //添加冷链报警事件
	            addColdChainAlarm(imei,speed, acc, compressor, door, lng, lat, t1, m1, calendar.getTime(), channelId);
	        }
	        //将最后一个;替换成,
	        int sbLen = sb.length();
	        if (sbLen > 0 && sb.charAt(sbLen - 1) == ';') {
	            sb.setCharAt(sbLen - 1, ',');
	        }
	        sb.append("s:").append(speed).append(',');
	        sb.append("of:").append(acc).append(compressor).append(door).append(",");
	        ctb.setProperties(sb.toString());
	        return ctb;
	    }

	    /**
	     * 添加冷链报警事件到List
	     * 
	     * @param speed
	     * @param acc
	     * @param compressor
	     * @param door
	     * @param lng
	     * @param lat
	     * @param t1
	     * @param m1
	     */
	    private void addColdChainAlarm(String imei, int speed, int acc, int compressor, int door, double lng, double lat, float t1, float m1, Date gatherTime, int num) {
	        CTBox12Alarm ctbox12Alarm = getCtbox12Alarm(imei, speed, acc, compressor, door, lng, lat, t1, m1, exception, gatherTime, num);
	        
	        //正常冷链信息
	        if (StringUtils.isBlank(exception)) {
	            coldChains.addNormal(ctbox12Alarm);
	            return;
	        }

	        //异常冷链信息
	        coldChains.addAlarm(ctbox12Alarm);
	    }

	    /**
	     * 获取CTBOX12报警事件
	     * @param speed
	     * @param acc
	     * @param compressor
	     * @param door
	     * @param lng
	     * @param lat
	     * @param t1
	     * @param m1
	     * @param exception
	     * @return
	     */
	    private CTBox12Alarm getCtbox12Alarm(String imei, int speed, int acc, int compressor, int door, double lng,
	                                         double lat, float t1, float m1, String exception,
	                                         Date gatherTime, int num) {
	        CTBox12Alarm ctbox12Alarm = new CTBox12Alarm();
	        ctbox12Alarm.setImei(imei);
	        ctbox12Alarm.setType(getAlarmType(exception));
	        ctbox12Alarm.setLat(lat);//lat
	        ctbox12Alarm.setLng(lng);//lng
	        ctbox12Alarm.setAlarm(getAlarmStatus(exception));
	        ctbox12Alarm.setSpeed(speed);//车辆行驶速度
	        ctbox12Alarm.setAcc(acc);//ACC状态
	        ctbox12Alarm.setCompressor(compressor);//压缩机状态
	        ctbox12Alarm.setDoor(door);//门开关
	        ctbox12Alarm.setAlarmt(t1);//温度值
	        ctbox12Alarm.setAlarmm(m1);//湿度
	        ctbox12Alarm.setCreatetime(new Date());//创建时间
	        ctbox12Alarm.setTime(gatherTime);//采集时间
	        ctbox12Alarm.setNum(num);

	        return ctbox12Alarm;
	    }

	    private void saveCTb(CTBox ctb) {
	        if(null == lctTraceManager){
	            logger.info("CTBOX02-冷链-0x12-设备:{} lctTraceManager is null..", ctb.getImei());
	            return;
	        }
	        
	        try {
	            lctTraceManager.insertCtbox12(ctb);
	        } catch (Exception e) {
	            logger.info("CTBOX02-冷链-0x12-设备:{} 数据进入到RocketMQ队列异常", ctb.getImei(), e);
	        } finally {
	            if(System.currentTimeMillis() - startTime > 30000){
	                startTime = System.currentTimeMillis();
	                logger.info("CTBOX02-冷链-0x12, imei:{}, properties:{}入RocketMQ队列", ctb.getImei(), ctb.getProperties());
	            }
	        }
	    }

	    /**
	     * 解析温度
	     * @param imei 
	     * 
	     * @param subData
	     * @param subIndex
	     * @return
	     */
	    private String analyTemperature(String imei, byte[] subData, Index subIndex) {
	        try {
	            //获取温度
	            byte[] res = { subData[subIndex.get() - 2], subData[subIndex.get() - 1] };
	            String checkValue = getMessageStr(res);
	            //logger.info("CTBOX02-冷链-0x12-获取设备:{}的温湿度值:{}", msg.getImei(), checkValue);

	            if (StringUtils.equals(checkValue, TemExceptionValue.EX_0XFFFD)) {
	                exception = checkValue;

	                //logger.info("CTBOX02-冷链-0x12-设备:{} 传感器正在初始化", msg.getImei());
	                return "--";
	            }

	            if (StringUtils.equals(checkValue, TemExceptionValue.EX_0XFFFE)) {
	                exception = checkValue;

	                //logger.info("CTBOX02-冷链-0x12-设备:{} 传感器故障", msg.getImei());
	                return "--";
	            }

	            if (StringUtils.equals(checkValue, TemExceptionValue.EX_0XFFFF)) {
	                exception = checkValue;

	                //logger.info("CTBOX02-冷链-0x12-设备:{} 无传感器", msg.getImei());
	                return "--";
	            }
	        } catch (Exception e) {
	            logger.info("CTBOX02-冷链-0x12-设备:{} 解析温湿度数据异常", imei);
	        }
	        return StringUtils.EMPTY;
	    }

	    /**当前有效温度异常值*/
	    interface TemExceptionValue {
	        /**传感器正在初始化*/
	        public String EX_0XFFFD = "FFFD";

	        /**传感器故障*/
	        public String EX_0XFFFE = "FFFE";

	        /**无传感器*/
	        public String EX_0XFFFF = "FFFF";
	    }

	    /**
	     * 获取报警类型
	     * 
	     * type 报警类型   0温度报警  1湿度报警 2传感器初始化中 3传感器故障 4 无传感器
	     * 
	     * @param exeception
	     * @return
	     */
	    private int getAlarmType(String exeception) {
	        if (StringUtils.equals(TemExceptionValue.EX_0XFFFD, exeception)) {
	            return 2;
	        }

	        if (StringUtils.equals(TemExceptionValue.EX_0XFFFE, exeception)) {
	            return 3;
	        }

	        if (StringUtils.equals(TemExceptionValue.EX_0XFFFF, exeception)) {
	            return 4;
	        }
	        return 0;
	    }

	    /**
	     * 获取报警状态
	     * 
	     * 报警状态    0 正常 1 低湿(低温)预警 2   低湿(低温)报警    3 高湿(高温)预警 4 高湿(高温)报警 5 传感器初始化中 6 传感器故障 7 无传感器
	     * 
	     * @param exeception
	     * @return
	     */
	    private int getAlarmStatus(String exeception) {
	        if (StringUtils.equals(TemExceptionValue.EX_0XFFFD, exeception)) {
	            return 5;
	        }

	        if (StringUtils.equals(TemExceptionValue.EX_0XFFFE, exeception)) {
	            return 6;
	        }

	        if (StringUtils.equals(TemExceptionValue.EX_0XFFFF, exeception)) {
	            return 7;
	        }
	        return 0;
	    }

	    /**
	     * 获取报文信息
	     * @param message
	     * @return
	     */
	    private static String getMessageStr(byte[] message) {
	        String result = "";
	        char[] chArr = Hex.encodeHex(message);
	        for (int i = 0; i < chArr.length; i++) {
	            result += String.valueOf(chArr[i]).toUpperCase();
	        }
	        return result;
	    }
	    
	    public void setLctTraceManager(LctTraceManager lctTraceManager) {
	        this.lctTraceManager = lctTraceManager;
	    }
}
